/**
 * 
 */
package boundary;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Image;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.beans.PropertyVetoException;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;

import javax.swing.JInternalFrame;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.event.InternalFrameAdapter;
import javax.swing.event.InternalFrameEvent;

import calculator.CoordinateManager;
import calculator.DialogBuilder;

import executor.QuadTree;

import boundary.components.CompressWindow;
import boundary.components.QuadTreeFileSaver;
import boundary.components.MyJLabel;
import boundary.components.MyJLabel.InsertingState;

/**
 * @author davide
 *
 */
public class ChildWindow extends JInternalFrame
{
    private static final long serialVersionUID = -5061629653835659322L;
    
    Container parent;		/** component container */
    String titlePrefix;		/** windows title prefix */
    MyJLabel container;		/** image container */
    CompressWindow compress;	/** compressing window */
    boolean needsToBeSaved;	/** do this window needs to be saved? */
    

    public ChildWindow(File f, Container ancestor) throws IllegalArgumentException
    {
	super("", true, true, true, true);
	this.setLayout(new BorderLayout());
	this.setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
	
	this.parent = ancestor;
	this.needsToBeSaved = false;
	this.setTitlePrefix(f.getName());

	this.parent.add(this);
	this.container = new MyJLabel(f, this);
	
	this.setContent();
	this.setVisible(true);
    }
    
    public ChildWindow(File f, Image image, Container ancestor) throws IllegalArgumentException
    {
	super("", true, true, true, true);
	this.setLayout(new BorderLayout());
	this.setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
	
	this.parent = ancestor;
	this.needsToBeSaved = false;
	this.setTitlePrefix(f.getName());

	this.parent.add(this);
	this.container = new MyJLabel(f, image, this);
	
	this.setContent();
	this.setVisible(true);
    }
    
    public ChildWindow(File f, QuadTree qtree, Container ancestor) throws IllegalArgumentException
    {
	super("", true, true, true, true);
	this.setLayout(new BorderLayout());
	this.setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
	
	this.parent = ancestor;
	this.needsToBeSaved = false;
	this.setTitlePrefix(f.getName());

	this.parent.add(this);
	this.container = new MyJLabel(f, qtree, this);
	
	this.setContent();
	this.setVisible(true);
    }
    
    public MyJLabel getContainer()
    {
        return this.container;
    }
    
    public CompressWindow getCompress()
    {
        return this.compress;
    }

    public void setNeedsToBeSaved(boolean itNeeds)
    {
        this.needsToBeSaved = itNeeds;
    }

    public void setTitlePrefix(String fname)
    {
	MainWindow.censusWindow(fname);
	
	int nItems =
	    MainWindow.howManyWindowsWithThatFile(fname);
	
	if(nItems > 1) {
	    this.titlePrefix = new String("(" + nItems + ") ");
	}
	
	else {
	    this.titlePrefix = new String("");
	}
    }
    
    @Override
    public void setTitle(String string)
    {
	if(this.needsToBeSaved == true) {
	    super.setTitle(this.titlePrefix + string + " *");
	}
	
	else {
	    super.setTitle(this.titlePrefix + string);
	}
    }

    private void setContent()
    {
	this.setFocusable(true);
	
	this.addInternalFrameListener(new InternalFrameAdapter() {
            @Override
            public void internalFrameClosing(@SuppressWarnings("unused") InternalFrameEvent e)
            {
        	if(ChildWindow.this.needsToBeSaved == true) {
        	    int n = DialogBuilder.createConfirmDialog(ChildWindow.this,
        		    "Esportare il file " + 
        		    ChildWindow.this.getContainer().getFile().getName() +
        		    " prima di uscire?", "Conferma Uscita");
        	    
        	    if(n == JOptionPane.YES_OPTION) {
        		ChildWindow.this.saveQuadTreeImage();
        	    }
        	}
        	
        	ChildWindow.this.dispose();
            }
	});
	
	this.addKeyListener(new KeyAdapter() {
	    @Override
            public void keyReleased(KeyEvent e)
            {
		if(e.getKeyCode() == KeyEvent.VK_ESCAPE) {
		    ChildWindow.this.container.cancelInsertion();
		}
            }
	});
	
	this.compress = new CompressWindow(
		"Toolbar per " + this.getContainer().getFile().getName(),
		this);
	
	//this.setContentPane(new JScrollPane(this.container));
	this.add(new JScrollPane(this.container), BorderLayout.CENTER);
	this.add(this.compress, BorderLayout.EAST);
	this.pack();
        
        if(this.container.getContent().getIconWidth() < 300) {
            this.setSize(300, this.getHeight());
        }
    }
    
    public Dimension getInternalFrameMaximumArea()
    {
	Dimension frameSize;
	
	try {
	    this.setMaximum(true);
	    frameSize = new Dimension(this.getWidth(), this.getHeight());
	    this.setMaximum(false);
	 } 
	
	catch (PropertyVetoException ex) {
	    frameSize = new Dimension(this.parent.getWidth(), this.parent.getHeight());
	 }
	
	return frameSize;
    }
    
    public void createQuadTreeSubdivisionImageWindow()
    {
	this.container.prepareQuadTreeImage();
	
	QuadTree qTree = this.container.getQuadTree();
	
	if(qTree != null)
	{
	    try {
		new ChildWindow(
			new File("div-" + this.getContainer().getFile().getName()),
			qTree.getSubdivisionImage(), this.parent);
	    }
	    
	    catch(Exception ex) {
		DialogBuilder.createErrorDialog(this.parent,
        		"Impossibile visualizzare l'immagine", "Errore");
	    }
	}
	
	MainWindow.menuShortcutsBugWorkaround();
    }
    
    public void createQuadTreeErrorImageWindow()
    {
	this.container.prepareQuadTreeImage();
	
	QuadTree qTree = this.container.getQuadTree();
	
	if(qTree != null)
	{
	    try {
		new ChildWindow(
			new File("err-" + this.getContainer().getFile().getName()),
			qTree.getErrorImage(), this.parent);
	    }
	    
	    catch(Exception ex) {
		DialogBuilder.createErrorDialog(this.parent,
        		"Impossibile visualizzare l'immagine", "Errore");
	    }
	}
	
	MainWindow.menuShortcutsBugWorkaround();
    }
    
    public void createQuadTreeImageWindow()
    {
	this.compress.setVisible(true);
	MainWindow.menuShortcutsBugWorkaround();
    }
    
    public void saveQuadTreeImage()
    {
	QuadTreeFileSaver fSaver =
	    new QuadTreeFileSaver(this.getContainer().getFile());
	
        if (fSaver.isValidSelection(this) == true) {
            this.launchQuadTreeSaveWindow(fSaver.getSelectedFile());
        }
        
        MainWindow.menuShortcutsBugWorkaround();
    }
    
    private void launchQuadTreeSaveWindow(File f)
    {
	OutputStream ostream;
	
	try {
	    ostream = new FileOutputStream(f);
	    
	    if(this.container.getInternalColor().equals(Color.black)
		    && this.container.getExternalColor().equals(Color.black))
	    {
		QuadTree.write(ostream, this.container.getQuadTree());
	    }
	    
	    else
	    {
		QuadTree.writeTaken(ostream, this.container.getQuadTree());
	    }
	    
	    this.needsToBeSaved = false;
        }
	
	catch(IOException ex) {
	    DialogBuilder.createErrorDialog(this.parent,
		    "Si è verificato un errore durante la scrittura su file",
		    "Errore Scrittura");
	}
    }
    
    private int getNextAvailableZoomFactor(int zFactor)
    {
	int factors[] = { 25, 50, 75, 100, 150, 200 };
	
	for(int i = 0; i < factors.length; ++i) {
	    if(factors[i] > zFactor) {
		return factors[i];
	    }
	    
	    if(factors[i] == zFactor) {
		if(i + 1 < factors.length) {
		    return factors[i + 1];
		}
		
		break;
	    }
	}
	
	return -1;
    }
    
    private int getPreviousAvailableZoomFactor(int zFactor)
    {
	int factors[] = { 25, 50, 75, 100, 150, 200 };
	
	for(int i = 0; i < factors.length; ++i) {	    
	    if(factors[i] >= zFactor) {
		if(i - 1 > -1) {
		    return factors[i - 1];
		}
		
		break;
	    }
	}
	
	return -1;
    }
    
    public void zoomImageIn()
    {
	int index = 
	    this.getNextAvailableZoomFactor(this.container.getZoomFactor());
	
	if(index > -1) {
	    this.container.scaleImageContent(index);
	}
	
	MainWindow.menuShortcutsBugWorkaround();
    }
    
    public void zoomImageOut()
    {
	int index = 
	    this.getPreviousAvailableZoomFactor(this.container.getZoomFactor());
	
	if(index > -1) {
	    this.container.scaleImageContent(index);
	}
	
	MainWindow.menuShortcutsBugWorkaround();
    }
    
    public void zoomImageFit()
    {
	this.container.scaleImageContent(-1);
	MainWindow.menuShortcutsBugWorkaround();
    }
    
    public void zoomImageOriginal()
    {
	this.container.scaleImageContent(100);
	MainWindow.menuShortcutsBugWorkaround();
    }
    
    public void drawActiveImage()
    {
	MyJLabel containerz = this.getContainer();
	
	switch (containerz.getInsertingState())
        {
		case INSERTING_NOTHING :
		case INSERTING_WAITING :
		{
		    containerz.getPolygon().reset();
		    containerz.getActiveImage().reset();
		    containerz.beginInsertingState(InsertingState.INSERTING_UPPERVX);
		    
		    containerz.repaint();
		    break;
		}

		default: {
		    break;
		}
        }
	
	MainWindow.menuShortcutsBugWorkaround();
    }
    
    public void eraseActiveImage()
    {
	MyJLabel containerz = this.getContainer();
	
	if(this.getCompress().isThisImageAlreadyCompressed) {
	    return;
	}
	
	switch (containerz.getInsertingState())
        {
		case INSERTING_NOTHING :
		case INSERTING_WAITING :
		{
		    containerz.setQuadTree(null);
		    containerz.getPolygon().reset();
		    containerz.getActiveImage().reset();
		    containerz.endInsertingState(InsertingState.INSERTING_NOTHING);
		    
		    containerz.repaint();
		    break;
		}

		default: {
		    break;
		}
        }
	
	MainWindow.menuShortcutsBugWorkaround();
    }
    
    public void maximizedTopActiveImage()
    {
	MyJLabel containerz = this.getContainer();
	
	switch (containerz.getInsertingState())
        {
		case INSERTING_NOTHING :
		case INSERTING_WAITING :
		{
		    containerz.getPolygon().reset();
		    containerz.getActiveImage().reset();
		    
		    containerz.getActiveImage().setLocation(0, 0,
			    containerz.getZoomFactor());
		    
		    containerz.getActiveImage().setLowerBoundAndClose(
			    containerz.getContentSize().width,
			    containerz.getContentSize().height,
			    containerz.getZoomFactor());
		    
		    containerz.endInsertingState(InsertingState.INSERTING_WAITING);
		    
		    containerz.repaint();
		    break;
		}

		default: {
		    break;
		}
        }
	
	MainWindow.menuShortcutsBugWorkaround();
    }
    
    public void maximizedBottomActiveImage()
    {
	MyJLabel containerz = this.getContainer();
	
	switch (containerz.getInsertingState())
        {
		case INSERTING_NOTHING :
		case INSERTING_WAITING :
		{
		    containerz.getPolygon().reset();
		    containerz.getActiveImage().reset();
		    
		    containerz.getActiveImage().setLocation(
			    containerz.getContentSize().width,
			    containerz.getContentSize().height,
			    containerz.getZoomFactor());
		    
		    containerz.getActiveImage().setLowerBoundAndClose(
			    0, 0, containerz.getZoomFactor());
		    
		    containerz.endInsertingState(InsertingState.INSERTING_WAITING);
		    
		    containerz.repaint();
		    break;
		}

		default: {
		    break;
		}
        }
	
	MainWindow.menuShortcutsBugWorkaround();
    }
    
    public void maximizedCenterActiveImage()
    {
	MyJLabel containerz = this.getContainer();
	
	switch (containerz.getInsertingState())
        {
		case INSERTING_NOTHING :
		case INSERTING_WAITING :
		{
		    int size;
		    containerz.getPolygon().reset();
		    containerz.getActiveImage().reset();
		    
		    if(containerz.getContentSize().width < containerz.getContentSize().height) {
			size = CoordinateManager.nearestLesserPowerOfTwo(containerz.getContent().getIconWidth());
		    }
		    
		    else {
			size = CoordinateManager.nearestLesserPowerOfTwo(containerz.getContent().getIconHeight());
		    }
		    
		    size = CoordinateManager.relativeCoord(size, containerz.getZoomFactor());
		    
		    containerz.getActiveImage().setLocation(
			    (containerz.getContentSize().width - size) / 2,
			    (containerz.getContentSize().height - size) / 2,
			    containerz.getZoomFactor());
		    
		    containerz.getActiveImage().setLowerBoundAndClose(
			    containerz.getContentSize().width,
			    containerz.getContentSize().height,
			    containerz.getZoomFactor());
		    
		    containerz.endInsertingState(InsertingState.INSERTING_WAITING);
		    
		    containerz.repaint();
		    break;
		}

		default: {
		    break;
		}
        }
	
	MainWindow.menuShortcutsBugWorkaround();
    }
    
    public void drawPolygon()
    {
	MyJLabel containerz = this.getContainer();
	
	if(containerz.getInsertingState() == InsertingState.INSERTING_WAITING) {
	    containerz.getPolygon().reset();
	    containerz.beginInsertingState(InsertingState.INSERTING_POLYGON);
	    
	    containerz.repaint();
	}
	
	MainWindow.menuShortcutsBugWorkaround();
    }
    
    public void erasePolygon()
    {
	MyJLabel containerz = this.getContainer();
	
	if(containerz.getInsertingState() == InsertingState.INSERTING_WAITING) {
	    containerz.getPolygon().reset();
	    
	    // real time update of compressin
	    if(this.getCompress().isVisible() ||
		    !this.getContainer().getInternalColor().equals(Color.black) ||
		    !this.getContainer().getExternalColor().equals(Color.black))
	    {
		this.getCompress().updateImage();
	    }
	    
	    containerz.repaint();
	}
	
	MainWindow.menuShortcutsBugWorkaround();
    }
}
